#include "CloneBot.h"

#include<map>
#include<set>
#include<utility>
#include<iostream>

using namespace std;

CloneBot::CloneBot()
{
	m_pxListSource = NULL;
	m_pxListClone = NULL;
}

void CloneBot::setSource(const FileList*  pxSourceList)
{
	m_pxListSource = const_cast<FileList*> (pxSourceList);
	m_pxListClone = new FileList;
}
void CloneBot::bySize()
{
	multimap<unsigned int, FileListItem*> m;
	set<unsigned int> anSizes;
	FileList* pxFileList = m_pxListSource;

	size_t n = pxFileList->m_apxItem.size();
	for(size_t i=0; i<n; i++ )
	{
		m.insert(pair<unsigned int, FileListItem*>(m_pxListSource->m_apxItem[i]->m_nSize, m_pxListSource->m_apxItem[i]));
		anSizes.insert(m_pxListSource->m_apxItem[i]->m_nSize);
	}

	set<unsigned int>::const_iterator pos;
    for(pos = anSizes.begin(); pos != anSizes.end(); ++pos)
	{
		if(m.count(*pos)>1)
		{
		   pair< multimap<unsigned int, FileListItem*>::iterator, multimap<unsigned int, FileListItem*>::iterator> ppp;

		   // equal_range(b) returns pair<iterator,iterator> representing the range
		   // of element with key b
		   ppp = m.equal_range(*pos);

		   // Loop through range of maps with key b
		   for (multimap<unsigned int, FileListItem*>::iterator it2 = ppp.first;
			   it2 != ppp.second;
			   ++it2)
		   {
			   m_pxListClone->m_apxItem..push_back((*it2).second);
		   }

		}
	}
}

void CloneBot::byName()
{
	multimap<string, FileListItem*> m;
	set<string> asNames;
	FileList* pxFileList = m_pxListSource;

	size_t n = pxFileList->m_apxItem.size();
	for(size_t i=0; i<n; i++ )
	{
		m.insert(
			pair<string, FileListItem*>
			(m_pxListSource->m_apxItem[i]->m_sName, m_pxListSource->m_apxItem[i])
			);
		asNames.insert(m_pxListSource->m_apxItem[i]->m_sName);
	}

	set<string>::const_iterator pos;
    for(pos = asNames.begin(); pos != asNames.end(); ++pos)
	{
		if(m.count(*pos)>1)
		{
		   pair< multimap<string, FileListItem*>::iterator, multimap<string, FileListItem*>::iterator> ppp;

		   // equal_range(b) returns pair<iterator,iterator> representing the range
		   // of element with key b
		   ppp = m.equal_range(*pos);

		   // Loop through range of maps with key b
		   for (multimap<string, FileListItem*>::iterator it2 = ppp.first;
			   it2 != ppp.second;
			   ++it2)
		   {
			   m_pxListClone->m_apxItem.push_back((*it2).second);
		   }

		}
	}
}

void CloneBot::findClones(FilterMode eFilterMode, bool bFilter)
{
	switch(eFilterMode)
	{
	case CloneBot::eBySize:
		bySize();
		break;

	case CloneBot::eByName:
		byName();
		break;
	}

}

void CloneBot::filterCurrentClones()
{
	m_pxListSource = m_pxListClone;
	m_pxListClone = new FileList;
}

void CloneBot::dump()
{
	size_t n = m_pxListClone->m_apxItem.size();
	unsigned long nTotalSize=0;

	if(n> 0)
		m_pxListClone->dump(nTotalSize);

	cout<<n<<" duplicates occupying "<< nTotalSize<<" bytes found in this hunt." << endl;
}






